<?php

/**
 * 易捷国际 SDK
 * @author chenyun
 */

namespace App\Service\VendorClient\Shopyijie;
use App\Model\PssModel\ServiceConfig;
use App\Service\Code\Normal;
use App\Service\TaskServer\TaskWorker;
use Service\AppService\IdService;
use Hyperf\Utils\WaitGroup;
use App\Model\PssModel\OrderSupplier;

class ShopyijieApiClient
{
    private $account  = 'Shopyijie';
    protected $config;
    protected $RouteMap = [
        'getAccessToken'       => '/api/login',
        'createOrder'          => '/rest',
        'orderPay'             => '/rest',
        'queryGoods'           => '/api',
        'queryGoodsStock'      => '/api',
        'queryGoodsDetail'     => '/api',
        'queryOrderExpress'    => '/rest',
    ];
    /**
     * 初始参数
     * @param obj $collection
     */
    public function __construct( $apiBody = [] ) 
    {
        $this->config = $apiBody;
    }

    /**
     * 创建订单
     */
    public function createOrder( $params = [] )
    {
        ini_set('serialize_precision', 16);
        
        if( empty($params['supplierOrder']) || empty($params['orderGoods']) || empty($params['order']) || empty($params['binfo']) ) {
            return Normal::returnCode(Normal::FAIL,"except param supplierOrder or orderGoods or order or binfo");
        }
        //组装订单参数
        $orderInfo = $params['supplierOrder'];
        $order     = $params['order'];
        $binfo     = $params['binfo'];
        //运费
        $deliver_money  = $orderInfo['deliver_money'];
        //商品下单组
        $orderItems = [];
        $productAmt     = $TaxAmt = 0 ;
        foreach ($params['orderGoods'] as $key => $item )
        {
            //卖价
            $price              = $item['price'];
            //商品购买规格数量
            $spec_num           = $item['spec_num'];
            //商品购买数量(下单数量 X 起售数量)
            $quantity           = $item['quantity'];
            //实际购买数量
            $buyAcount          = $spec_num * $quantity ;
            //如果商品除不尽，得多取以为，减去实际金额为折扣，折扣不能为负数
            if( $key == 0 ) {
                $singleDeliveryMoney = bcdiv((string)$deliver_money,(string)$quantity,3);
                $singleDeliveryMoney = bcmul((string)$singleDeliveryMoney,(string)100,1);
                $singleDeliveryMoney = bcdiv((string)ceil($singleDeliveryMoney), (string)100,2);
                $price               = bcadd((string)$price, (string)$singleDeliveryMoney,2);
            }
            //单个商品价格
            $singleGoodsPrice   = bcdiv((string)$price, (string)$spec_num,3);
            $singleGoodsPrice   = ceil(bcmul((string)$singleGoodsPrice,(string)'100',1));
            $singleGoodsPrice   = bcdiv((string)$singleGoodsPrice,'100',2);
            $totalGoods         = bcmul((string)$singleGoodsPrice,(string)$buyAcount,2);
        
            //含税税率
            $tax_rate           = bcadd('1', (string)$item['tax_rate'],4);
        
            //不含税价格
            $not_tax_price      = bcdiv((string)$singleGoodsPrice, (string)$tax_rate,3);
            // echo "含税税率:".$tax_rate."不含税价格：".$not_tax_price;
            $not_tax_price      = ceil(bcmul((string)$not_tax_price,(string)'100',1));
            // echo "含税税率:".$tax_rate."不含税价格：".$not_tax_price;
            $not_tax_price      = bcdiv((string)$not_tax_price,'100',2);
        
            //税金
            $singleGoodsTax     = bcsub((string)$singleGoodsPrice, (string)$not_tax_price,3);
        
            //单个商品总税金
            $totalGoodsTax  = bcmul((string)$singleGoodsTax,(string)$buyAcount,2);
        
            //单个商品总含税价格
            $totalGoods     = bcmul((string)$not_tax_price,(string)$buyAcount,2);
        
            //商品组
            $orderItems[] = [
                "skuCode"       => $item['supplier_skucode'],
                "qty"           => $buyAcount,
                "salesPrice"    => $not_tax_price,
            ];
            $productAmt = bcadd((string)$productAmt,(string)$totalGoods,2);
            $TaxAmt = bcadd((string)$TaxAmt,(string)$totalGoodsTax,2);
        }
        
        //实际下单金额
        $real_total_money = $orderInfo['real_total_money'];
        //订单总金额 = 不含税商品总金额 + 总税费 + 运费 - 优惠金额
        $ActualPaidAmt  = bcadd((string)$productAmt,(string)$TaxAmt,2);
        $ActualPaidAmt  = bcadd((string)$ActualPaidAmt,(string)$deliver_money,2);
        //优惠金额
        $discount_money = bcsub((string)$ActualPaidAmt,$real_total_money,2);

        $data = [
            'memberPhone'           => $orderInfo['recveive_phone'],
            'companyId'             => $this->config["companyId"],
            'xmhOrderNo'            => $orderInfo['supplier_dsn'],
            'xmhOrderTotal'         => $real_total_money,
            'discountAmount'        => $discount_money,
            'xmhTaxTotal'           => $TaxAmt,
            'feeDivide'             => 0.00,
            'receiverName'          => $orderInfo['receive_name'],
            'receiverPhone'         => $orderInfo['recveive_phone'],
            'receiverState'         => $orderInfo['province'],
            'receiverCity'          => $orderInfo['city'],
            'receiverDistrict'      => $orderInfo['district'],
            'receiverAddress'       => $orderInfo['receive_address'],
            'shoppingCartList'      => $orderItems,
            'memberCertification'   => [
                'realName' => $orderInfo['buyer_realname'],
                'idNumber' => $orderInfo['buyer_idcard']
            ]
        ];
        $requestParam = [
            'method'    => 'createOrder',
            'data'      => [
                'method'        => "XinManHuiCreateOrder",
                'timestamp'     => date("Y-m-d H:i:s",time()),
                'version'       => "1",
                'data'          => $data,
            ],
        ];
        
        $result    = $this->execute($requestParam);
        if($result["code"] != Normal::SUC){
            return $result;
        }
        return $this->orderPay($params);
    }

    /**
     * 订单支付
     * @param array $params
     * @return mixed
     */
    public function orderPay( $params = [] )
    {
        $orderSupplier      = $params['supplierOrder'];
        $order              = $params['order'];

        $mer_order_sn       = $orderSupplier['supplier_dsn'];

        //支付拓展信息
        $apply_extends      = @json_decode($orderSupplier['apply_extends'],true);
        $apply_extends      = empty($apply_extends) ? $order : $apply_extends;
        $payTime="";
        //支付时间
        if(isset($apply_extends['payTime']) && empty($apply_extends['payTime'])){
            $payTime = $apply_extends['pay_time'];
        }
        if(isset($order['payTime']) && empty($order['payTime'])){
            $payTime = $order['pay_time'];
        }
        $pay_time       = $payTime ? $payTime : time();

        //支付流水号
        $pay_sn         = $orderSupplier['pay_sn'];
        $pay_sn         = $pay_sn ? $pay_sn : $order["paySerial"];
        
        //下单支付的时候支付信息
        $apply_extends  = @json_decode($orderSupplier['apply_extends'],true);
        //获取上游供应商支付方式路由
        $payCommanyCode = $apply_extends['payCommanyCode'] ?? '';
        $payCommanyCode = $order['payCommanyCode'] ? $order['payCommanyCode'] : $payCommanyCode;
        $payCommanyName = $apply_extends['payCommanyName'] ?? '';
        $payCommanyName = $order['payCommanyName'] ? $order['payCommanyName'] : $payCommanyName;

        $enterpriseNum = $apply_extends['enterpriseNum'] ?? '';
        $enterpriseNum = $order['enterpriseNum'] ? $order['enterpriseNum'] : $enterpriseNum;
        $enterpriseName = $apply_extends['enterpriseName'] ?? '';
        $enterpriseName = $order['enterpriseName'] ? $order['enterpriseName'] : $enterpriseName;
        $pay_value      = ServiceConfig::instance()->getConfigByEventsValue($this->account, ServiceConfig::TYPE_PAY, $payCommanyCode);
        if (empty($pay_value)) {
            return Normal::returnCode(Normal::FAIL, "支付公司编码：【{$payCommanyCode}】未映射，请联系管理员处理");
        }
        //支付订单数据
        $data = [
            'transactionNo'   => $pay_sn,
            'payCompanyName'  => $payCommanyName,
            'payCompanyNum'   => $payCommanyCode,
            'enterpriseNum'   => $enterpriseNum,
            'enterpriseName'  => $enterpriseName,
            'paymentWay'      => $pay_value,
            'xmhOrderNo'      => $orderSupplier['supplier_dsn'],
            'orderStatus'     => "PAYED",
            'payTime'         => (string)$pay_time,
        ];
        $requestParam = [
            'method'    => 'orderPay',
            'data'      => [
                'method'        => "XMHUpdateOrderStatus",
                'timestamp'     => date("Y-m-d H:i:s",time()),
                'version'       => "1",
                'data'          => $data,
            ],
        ];
        $res    = $this->execute($requestParam);
        return $res;
    }
    /**
     * 获取取消订单
     */
    public function cancelOrder( $params = [] ) 
    {
        return Normal::returnCode(Normal::SUC,"处理成功");
    }
    /**
     * 查询物流单信息
     * @param array $param
     */
    public function queryOrderExpress( $param = [] )
    {
        //查询你订单物流数据
        $data = [
            'xmhOrderNo'    => $param['supplier_dsn']
        ];
        $requestParam = [
            'method'    => 'queryOrderExpress',
            'data'      => [
                'method'        => "XMHDeliveryQuery",
                'timestamp'     => date("Y-m-d H:i:s",time()),
                'version'       => "1",
                'data'          => $data,
            ],
        ];
        $res    = $this->execute($requestParam);
        return $res;
    }
    
    /**
     * 查询商品详情
     */
    public function queryGoodsList($param)
    {
        //获取token
        $access_token = $this->getAccessToken();
        if($access_token["code"] != Normal::SUC){
            return $access_token;
        }
        $this->token = $access_token["data"];
        $limit  = 50;
        $start  = 0;
        if(isset($param["limit"])){
            $limit = $param["limit"];
        }
        if($param["page"]==1){
            $param["page"] = 0;
        }
        $start = bcmul($param["page"], $limit);
        $data = [
            'salesBranchId' => $this->config["salesBranchId"],
            'start'         => (int)$start,
            'limit'         => (int)$limit,
        ];
        $requestParam = [
            'method'    => 'queryGoods',
            'data'      => [
                'method'        => "platformItemList",
                'timestamp'     => date("Y-m-d H:i:s",time()),
                'version'       => "1",
                'token'         => $this->token,
                'data'          => json_encode($data,JSON_UNESCAPED_UNICODE),
            ],
        ];
        $res  = $this->curlExecute($requestParam);
        if( $res["code"] != Normal::SUC) 
        {
            return $res;
        }
        
        if( empty($res["data"]["results"]) ) {
            return Normal::returnCode(Normal::SUC,"拉取完成，无数据了!");
        }
        
        $goodsList =[];
        foreach ($res["data"]["results"] as $g =>$good)
        {
            foreach ($good["skus"] as $k =>$v){
                $goodsList[] = [
                    'skuCode'               => $v["skuCode"],//主图
                    'skuType'               => $v["skuType"],//类型
                    'itemName'              => $v["itemName"],//名字
                    'defaultImgUrl'         => $good["defaultImgUrl"],//主图
                    'pcIntro'               => $good["pcIntro"],//pc详情图
                    'categoryName'          => $good["categoryName"],
                    'brandName'             => $good["brandName"],
                    'minBuy'                => $good["minBuy"],//最小购买数量
                    'skuNumber'             => $good["skuNumber"],//规格数
                    'onShelf'               => $good["onShelf"],//true等于上架
                    'barcode1'              => $good["barcode1"],//条形码 
                    'unit'                  => $good["unit"],//单位
                    'oriCountry'            => $v["oriCountry"],//原产国
                    'weight'                => $good["weight"],//重量
                    'addTaxRate'            => $v["addTaxRate"],//增值税税率
                    'exciseTaxRate'         => $v["exciseTaxRate"],//消费税税率
                    'exciseTaxLowestPrice'  => $v["exciseTaxLowestPrice"],//触发消费税的最小销售价
                ];
            }
        }
        $details    = [];
        $size       = $this->config['limit'] ?? 100;
        $chunkArr   = array_chunk($goodsList,$size);
        foreach ($chunkArr as $skuNos) 
        {   
            $wg = new WaitGroup();
            $count = count($skuNos);
            $wg->add($count);
            foreach ($skuNos as $s => $sku)
            {
                co(function () use ($wg,$sku, & $details) 
                {     
                    $qty = 0;
                    $stockPrice = 0;
                    //查询库存信息
                    $stockWhere = [
                        'salesBranchId' => $this->config["salesBranchId"],
                        'skuCodes'      => [$sku["skuCode"]],
                        'start'         => $param["page"]??0,
                        'limit'         => $param["limit"]??100,
                    ];
                    $requestParam = [
                        'method'    => 'queryGoodsStock',
                        'data'      => [
                            'method'        => "platformSkuStock",
                            'timestamp'     => date("Y-m-d H:i:s",time()),
                            'version'       => 1,
                            'token'         => $this->token,
                            'data'          => json_encode($stockWhere,JSON_UNESCAPED_UNICODE),
                        ],
                    ];
                    $responseParam = $this->curlExecute($requestParam);
                    if ($responseParam['code']== Normal::SUC && isset($responseParam['data']['results']))
                    {
                        $stockInfo = $responseParam['data']['results'][0];
                        $qty = $stockInfo["qty"];
                        $stockPrice = $stockInfo["stockPrice"];
                    }
                    $sku["qty"]  = $qty;
                    $sku["stockPrice"]  = $stockPrice;
                    $details[]= $sku;
                    $wg->done();
                });
            }
            $wg->wait();
        }
        
        return Normal::returnCode(Normal::SUC,"获取成功",[
            'total' => $res['data']['total'],
            'list'  => $details
        ]);
    }
    /**
     * 查询token值
     * @param array $param
     */
    public function getAccessToken( $param = [] )
    {
        $redis = redis();
        $cache_key = $this->account."_AccessToken";
        $AccessToken = $redis->get($cache_key);
        $is_token = 0;
        if(empty($AccessToken)){
            $is_token = 1;
        }
        $TokenInfo = json_decode($AccessToken,true);
        $token    = $TokenInfo["apiToken"];
        if(strtotime($TokenInfo["expireTime"]) <= time()){
            $is_token = 1;
        }
        if($is_token == 1){
            $data = [
                'username'      => $this->config["username"],
                'password'      => base64_encode($this->config["password"]),
                'timestamp'     => date("Y-m-d H:i:s",time()),
                'version'       => 2
            ];
            $requestParam = [
                'method'    => 'getAccessToken',
                'data'      => $data
            ];
            $res =  $this->curlExecute($requestParam);
            if( $res['code'] != Normal::SUC ) {
                return $res;
            }
            $AccessToken = json_encode($res["data"],JSON_UNESCAPED_UNICODE);
            $token = $res["data"]["apiToken"];
            $redis->set($cache_key,$AccessToken);
        }
        return Normal::returnCode(Normal::SUC,"获取成功",$token);
    }
    /**
     * 加签
     * @param array $param
     */
    protected function getSign( $params = [] )
    {
        $string = "";
        //第一步：排序
        ksort($params);
        //第二步：按照key + value 的格式组装
        foreach ($params as $k => $v){
            $string.=$k.$v;
        }
        //第三步：将秘钥跟字符串组成新的字符串
        $string = $this->config["secret"].$string;
        //第四步：md5
        $string=md5($string);
        //第五步：md5转大写
        return strtoupper($string);
    }
    
    /**
     * 加签
     * @param array $param
     */
    protected function orderGetSign( $params = [] )
    {
        $string = "";
        //第一步：排序
        ksort($params);
        //第二步：按照key + value 的格式组装
        foreach ($params as $k => $v){
            if($k == "data"){
                $string.= $k.stripslashes(json_encode($v,JSON_UNESCAPED_UNICODE));
            }else{
                $string.=$k.$v;
            }
        }
        //第三步：将秘钥跟字符串组成新的字符串
        $string = $this->config["secretKey"].$string;
        //第四步：md5
        $string=md5($string); 
        //第五步：md5转大写
        return strtoupper($string);
    }
    
    /**
     * CURL请求
     * @param $params
     * @return mixed
     */
    public function curlExecute( $param = [] )  
    {
        if( empty($param['data']) ) {
            return Normal::returnCode(Normal::FAIL,"数据不能为空");
        }

        $method = $param['method'];
        $url    =$this->config["baseurl"].$this->RouteMap[$method];
        $param['data']["sign"]= $this->getSign($param["data"]);
        $parameter = [
            [
                'tag'       => $this->account.'_'.$method,
                'uid'       => IdService::instance()->getOtherID(),
                'url'       => $url,
                'data'      => $param['data'],
                'method'    => 'post',
                'format'    => '',
                'header'    => [],
        
            ],
        ];
        $resTask = TaskWorker::instance()->addTask($parameter,'handleDiableTask');
        $resTask = current($resTask);
        $res     = $resTask['response']['result'];
        $resHttp = json_decode($res,true);
        if( isset($resHttp['success']) && $resHttp['success'] == true ) {
            return Normal::returnCode(Normal::SUC,"操作成功",$resHttp["data"]);
        }
        $errorMessage = isset($resHttp['errorMessage']) ? $resHttp['errorMessage'] : '';
        $message = isset($resHttp['message']) ? $resHttp['message'] : '';
        $message = $message ? $message : $errorMessage;
        $message = $message ? $message : "请求失败";
        return Normal::returnCode(Normal::FAIL,$message);
    }
    /**
     * CURL请求
     * @param $params
     * @return mixed
     */
    public function execute( $param = [] )
    {
        if( empty($param['data']) ) {
            return Normal::returnCode(Normal::FAIL,"数据不能为空");
        }
    
        $method = $param['method'];
        $url    =$this->config["baseurl"].$this->RouteMap[$method];
        $param['data']["sign"]= $this->orderGetSign($param["data"]);
        $parameter = [
            [
                'tag'       => $this->account.'_'.$method,
                'uid'       => IdService::instance()->getOtherID(),
                'url'       => $url,
                'data'      => $param['data'],
                'method'    => 'post',
                'format'    => 'json',
                'header'    => ["Content-Type: application/json"],
    
            ],
        ];
        $resTask = TaskWorker::instance()->addTask($parameter);
        $resTask = current($resTask);
        $res     = $resTask['response']['result'];
        $resHttp = json_decode($res,true);
        if( isset($resHttp['success']) && $resHttp['success'] == true ) {
            $data = is_array($resHttp['data'])? $resHttp['data'] : [];
            return Normal::returnCode(Normal::SUC,"请求成功",$data);
        }
        $message = $resHttp["errorMessage"] ? $resHttp["errorMessage"] : $resHttp["message"];
        $message = $message ??"";
        return Normal::returnCode(Normal::FAIL,"上游供应商返回【".$message."】");
    }
}